/**
 * Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/daikit4gxt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.daikit4gxt.client.ui.popup;

import com.daikit.commons.shared.bean.AbstractDkBeanWithId;
import com.daikit.commons.shared.bean.AbstractDkModifiableBeanWithId;
import com.daikit.commons.shared.exception.DkUnsupportedMethodException;
import com.daikit.commons.shared.miscs.Couple;
import com.daikit.daikit4gxt.client.DkMain;
import com.daikit.daikit4gxt.client.action.BaseAction;
import com.daikit.daikit4gxt.client.action.BaseAsyncCallback;
import com.daikit.daikit4gxt.client.editor.DkClearValidationVisitor;
import com.daikit.daikit4gxt.client.editor.DkPreFlushVisitor;
import com.daikit.daikit4gxt.client.editor.DkSimpleBeanEditorDriver;
import com.daikit.daikit4gxt.client.log.BaseLogger;
import com.daikit.daikit4gxt.client.ui.UIInvalidatable;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.user.client.Timer;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.TreeStore;


/**
 * A class to extend for Dialog box for edition or creation of bean
 * 
 * @author tcaselli
 * @version $Revision$ Last modifier: $Author$ Last commit: $Date$
 * @param <BEANTYPE>
 *           edited bean type
 * @param <EDITORTYPE>
 *           {@link Editor} type (editor for type B)
 * @param <STORETYPE>
 *           the type of the grid to which the bean should then bean added or updated
 */
public abstract class MyEditCreateProxyPopup<BEANTYPE extends AbstractDkBeanWithId, STORETYPE extends AbstractDkBeanWithId, EDITORTYPE extends Editor<BEANTYPE>>
		extends MyFormDialog implements UIInvalidatable
{

	protected BaseLogger log = BaseLogger.getLog(getClass());

	private ListStore<STORETYPE> store;
	private TreeStore<STORETYPE> treeStore; // only one of store and treeStore is useful at the same time
	private final EDITORTYPE editor;
	private boolean isCreation = false;
	private BEANTYPE model;
	private BEANTYPE newInstanceForCreation;

	protected STORETYPE treeParentModel;
	protected int index = 0;
	protected MyEditCreatePopupShowCallback<BEANTYPE, STORETYPE, EDITORTYPE> callback;

	@SuppressWarnings("rawtypes")
	private DkSimpleBeanEditorDriver driver;

	protected String labelCorrectErrorsTitle = DkMain.i18n().error_validation_popup_correct_fields_before_save_title();
	protected String labelCorrectErrorsMessage = DkMain.i18n().error_validation_popup_correct_fields_before_save_message();

	protected MyEditCreateProxyPopup(final EDITORTYPE editor)
	{
		super(false, 1, DisplayableButton.SAVE, DisplayableButton.RESET, DisplayableButton.CANCEL);
		this.editor = editor;
	}

	/**
	 * Use one of these methods instead:
	 * <ul>
	 * <li>{@link #showForUpdate(ListStore, AbstractDkBeanWithId)}</li>
	 * <li>{@link #showForUpdate(TreeStore, AbstractDkBeanWithId)}</li>
	 * <li>
	 * {@link #showForUpdate(ListStore, AbstractDkBeanWithId)}</li>
	 * <li>
	 * {@link #showForUpdate(TreeStore, AbstractDkBeanWithId)}</li>
	 * <li>{@link #showForCreation()}</li>
	 * <li>{@link #showForCreation(ListStore)}</li>
	 * <li>
	 * {@link #showForCreation(MyEditCreatePopupShowCallback)}</li>
	 * <li>{@link #showForCreation(ListStore, MyEditCreatePopupShowCallback)}</li>
	 * <li>
	 * {@link #showForCreation(TreeStore, AbstractDkBeanWithId)}</li>
	 * </li>
	 * <li>
	 * {@link #showForCreation(TreeStore, AbstractDkBeanWithId, int)}</li>
	 * </li>
	 * <li>
	 * {@link #showForCreation(TreeStore, AbstractDkBeanWithId, MyEditCreatePopupShowCallback)}</li>
	 * </li>
	 * <li>
	 * {@link #showForCreation(TreeStore, AbstractDkBeanWithId, int, MyEditCreatePopupShowCallback)}</li>
	 * </li>
	 * </ul>
	 */
	@Deprecated
	@Override
	public void show()
	{
		throw new DkUnsupportedMethodException("This method must not be called directly. See javadoc for details.");
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// SHOW FOR UPDATE
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	/**
	 * Show the Dialog box for edition of the given model with no callback
	 * 
	 * @param store
	 *           the Store
	 * @param model
	 *           the model to be edited
	 */
	public void showForUpdate(final ListStore<STORETYPE> store, final BEANTYPE model)
	{
		showForUpdate(store, model, null);
	}

	/**
	 * Show the Dialog box for edition of the given model with no callback
	 * 
	 * @param treeStore
	 *           the TreeStore
	 * @param model
	 *           the model to be edited
	 */
	public void showForUpdate(final TreeStore<STORETYPE> treeStore, final BEANTYPE model)
	{
		showForUpdate(treeStore, model, null);
	}

	/**
	 * Show the Dialog box for edition of the given model
	 * 
	 * @param store
	 *           the Store
	 * @param model
	 *           the model to be edited
	 * @param callback
	 *           the {@link MyEditCreatePopupShowCallback} callback
	 */
	public void showForUpdate(final ListStore<STORETYPE> store, final BEANTYPE model,
			final MyEditCreatePopupShowCallback<BEANTYPE, STORETYPE, EDITORTYPE> callback)
	{
		this.store = store;
		this.treeStore = null;
		this.callback = callback;
		initializeForEdition(model);
	}

	/**
	 * Show the Dialog box for edition of the given model
	 * 
	 * @param treeStore
	 *           the TreeStore
	 * @param model
	 *           the model to be edited
	 * @param callback
	 *           the {@link MyEditCreatePopupShowCallback} callback
	 */
	public void showForUpdate(final TreeStore<STORETYPE> treeStore, final BEANTYPE model,
			final MyEditCreatePopupShowCallback<BEANTYPE, STORETYPE, EDITORTYPE> callback)
	{
		this.store = null;
		this.treeStore = treeStore;
		this.callback = callback;
		initializeForEdition(model);
	}

	/**
	 * Called by {@link #showForUpdate(ListStore, AbstractDkBeanWithId)} after setting the store. Factor code for
	 * constructor with ListStore and TreeStore
	 * 
	 * @param optionalArgs
	 */
	protected void initializeForEdition(final BEANTYPE model)
	{
		isCreation = false;
		this.model = model;
		this.newInstanceForCreation = null;
		this.index = 0;
		this.treeParentModel = null;
		onBeforeShow();
		super.show();
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// SHOW FOR CREATION
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	/**
	 * Show the Dialog box for creation of a new model without store, so without possibility to add the created instance
	 * to any grid.
	 */
	public void showForCreation()
	{
		showForCreation((ListStore<STORETYPE>) null, null);
	}

	/**
	 * Show the Dialog box for creation of a new model without store, so without possibility to add the created instance
	 * to any grid.
	 * 
	 * @param callback
	 *           the {@link MyEditCreatePopupShowCallback} callback
	 */
	public void showForCreation(final MyEditCreatePopupShowCallback<BEANTYPE, STORETYPE, EDITORTYPE> callback)
	{
		showForCreation(null, callback);
	}

	/**
	 * Show the Dialog box for creation of a new model with no callback
	 * 
	 * @param store
	 *           the Store
	 */
	public void showForCreation(final ListStore<STORETYPE> store)
	{
		showForCreation(store, null);
	}

	/**
	 * Show the Dialog box for creation of a new model
	 * 
	 * @param store
	 *           the Store
	 * @param callback
	 *           the {@link MyEditCreatePopupShowCallback} callback
	 */
	public void showForCreation(final ListStore<STORETYPE> store,
			final MyEditCreatePopupShowCallback<BEANTYPE, STORETYPE, EDITORTYPE> callback)
	{
		this.store = store;
		this.treeStore = null;
		this.index = 0;
		this.treeParentModel = null;
		this.callback = callback;
		initializeForCreation();
	}

	/**
	 * Show the Dialog box for creation of a new model with no save/show callback
	 * 
	 * @param treeStore
	 *           the TreeStore
	 * @param treeParent
	 *           the parent model in which the created entry will be added
	 */
	public void showForCreation(final TreeStore<STORETYPE> treeStore, final STORETYPE treeParent)
	{
		showForCreation(treeStore, treeParent, null);
	}

	/**
	 * Show the Dialog box for creation of a new model
	 * 
	 * @param treeStore
	 *           the TreeStore
	 * @param treeParent
	 *           the parent model in which the created entry will be added
	 * @param callback
	 *           the {@link MyEditCreatePopupShowCallback} callback
	 */
	public void showForCreation(final TreeStore<STORETYPE> treeStore, final STORETYPE treeParent,
			final MyEditCreatePopupShowCallback<BEANTYPE, STORETYPE, EDITORTYPE> callback)
	{
		showForCreation(treeStore, treeParent, 0, callback);
	}

	/**
	 * Show the Dialog box for creation of a new model with no save/show callback
	 * 
	 * @param treeStore
	 *           the TreeStore
	 * @param treeParent
	 *           the parent model in which the created entry will be added
	 * @param index
	 *           the index where to add the created element within parent
	 */
	public void showForCreation(final TreeStore<STORETYPE> treeStore, final STORETYPE treeParent, final int index)
	{
		showForCreation(treeStore, treeParent, index, null);
	}

	/**
	 * Show the Dialog box for creation of a new model
	 * 
	 * @param treeStore
	 *           the TreeStore
	 * @param treeParent
	 *           the parent model in which the created entry will be added
	 * @param index
	 *           the index where to add the created element within parent
	 * @param callback
	 *           the {@link MyEditCreatePopupShowCallback} callback
	 */
	public void showForCreation(final TreeStore<STORETYPE> treeStore, final STORETYPE treeParent, final int index,
			final MyEditCreatePopupShowCallback<BEANTYPE, STORETYPE, EDITORTYPE> callback)
	{
		this.store = null;
		this.treeStore = treeStore;
		this.index = index;
		this.treeParentModel = treeParent;
		this.callback = callback;
		initializeForCreation();
	}

	/**
	 * Called by {@link #showForCreation(ListStore)} after setting the store. Factor code for constructor with ListStore
	 * and TreeStore
	 * 
	 * @param optionalArgs
	 */
	protected void initializeForCreation()
	{
		isCreation = true;
		final BEANTYPE newModelForCreation = getNewInstanceForCreation();
		final BEANTYPE newBean = newModelForCreation == null ? createBeanInstance() : newModelForCreation;
		if (newBean instanceof AbstractDkModifiableBeanWithId)
		{
			((AbstractDkModifiableBeanWithId) newBean).setCreation(true);
		}
		this.model = newBean;
		this.index = 0;
		onBeforeShow();
		super.show();
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// RPC
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	protected void callCreateOrUpdateRpc(final BEANTYPE bean, final BaseAsyncCallback<BEANTYPE> callback)
	{
		if (isCreation())
		{
			callCreateRpc(bean, callback);
		}
		else
		{
			callUpdateRpc(bean, callback);
		}
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// ABSTRACT METHODS
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	protected abstract BEANTYPE createBeanInstance();

	protected abstract void callCreateRpc(BEANTYPE bean, BaseAsyncCallback<BEANTYPE> callback);

	protected abstract void callUpdateRpc(BEANTYPE bean, BaseAsyncCallback<BEANTYPE> callback);

	/**
	 * For more information about GWT Editor :<br>
	 * <a href="https://developers.google.com/web-toolkit/doc/latest/DevGuideUiEditors">
	 * https://developers.google.com/web-toolkit/doc/latest/DevGuideUiEditors</a>
	 * 
	 * @return the editor driver
	 */
	protected abstract DkSimpleBeanEditorDriver<BEANTYPE, EDITORTYPE> getDriver();

	/**
	 * May be overridden if you need an action to convert the result data (you can get it within you action using
	 * {@link BaseAction#getPreviousActionResult()}). This action will be added to the chain after save Action.
	 * 
	 * @return null if not needed, an action otherwise.
	 */
	protected BaseAction<STORETYPE> getConvertResultAction()
	{
		return null;
	}

	/**
	 * May be overridden if you need an action to be executed right after saving (before
	 * {@link #getConvertResultAction()})
	 * 
	 * @return a {@link BaseAction} or null
	 */
	protected BaseAction<BEANTYPE> getPostSaveAction()
	{
		return null;
	}

	/**
	 * Method to be overridden to provide possibility to add children of the modelToAdd
	 * 
	 * @param treeStore
	 *           the {@link TreeStore}
	 * @param parentModel
	 *           the former parent model (may be the same or may have changed during edition)
	 * @param modelIndexInFormerParentModel
	 *           the index where to add the model within the former parentModel (if -1 the add to the end) (not relevant
	 *           if parent model has changed during update)
	 * @param modelToAdd
	 *           the model to add
	 */
	protected void addModelToTreeStore(final TreeStore<STORETYPE> treeStore, final STORETYPE parentModel,
			final int modelIndexInParent, final STORETYPE modelToAdd)
	{
		if (parentModel == null)
		{
			treeStore.add(modelToAdd);
		}
		else
		{
			if (modelIndexInParent != -1)
			{
				treeStore.insert(parentModel, modelIndexInParent, modelToAdd);
			}
			else
			{
				treeStore.add(parentModel, modelToAdd);
			}
		}
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// PSEUDO EVENT MECHANISM
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	protected void onBeforeDriverEdit()
	{
		// Nothing done by default.
	}

	protected void doDriverEdit()
	{
		onBeforeDriverEdit();
		setHeadingText(getLabelPopupTitle());
		getSetupDriver().accept(new DkClearValidationVisitor());
		if (callback != null)
		{
			callback.onBeforeDriverEdit(model, getSetupDriver());
		}
		getSetupDriver().edit(null);
		getSetupDriver().edit(model);
		if (callback != null)
		{
			callback.onAfterDriverEditBeforeShow(editor, getSetupDriver());
		}
		onAfterDriverEdit();
	}

	protected void onAfterDriverEdit()
	{
		// Nothing done by default.
	}

	protected void onBeforeShow()
	{
		doDriverEdit();
	}

	protected void onCancel()
	{
		// store.rejectChanges();
	}

	protected void onAfterSave(final STORETYPE storeTypeResult)
	{
		if (isCreation())
		{
			if (getStore() != null)
			{
				getStore().add(0, storeTypeResult);
			}
			else if (getTreeStore() != null)
			{
				if (treeParentModel == null)
				{
					getTreeStore().add(storeTypeResult);
				}
				else
				{
					addModelToTreeStore(getTreeStore(), treeParentModel, -1, storeTypeResult);
				}
			}
		}
		else
		{
			if (getStore() != null)
			{
				final int modelIndex = getStore().indexOf(storeTypeResult);
				getStore().remove(modelIndex);
				getStore().add(modelIndex, storeTypeResult);
			}
			else if (getTreeStore() != null)
			{
				final int modelIndexInFormerParentModel = getTreeStore().indexOf(storeTypeResult);
				final STORETYPE formerParentModel = getTreeStore().getParent(storeTypeResult);
				getTreeStore().remove(storeTypeResult);
				final Couple<STORETYPE, Integer> couple = getNewParentModelAndIndexAfterSave(treeStore, formerParentModel,
						modelIndexInFormerParentModel, storeTypeResult);
				addModelToTreeStore(getTreeStore(), couple.first, couple.second, storeTypeResult);
			}
		}
		if (callback != null)
		{
			callback.onAfterSave(storeTypeResult);
		}
		// store.commitChanges();
		hide();
	}

	/**
	 * Override this method to calculate the new parent model and index within parent of the saved item (in case of a
	 * {@link TreeStore} ). By default this method returns the former parent model and former index. The saved item will
	 * be removed from former parent and added to the new one.
	 * 
	 * @param treeStore
	 *           the {@link TreeStore} in which the model has to be added updated save
	 * @param modelIndexInFormerParentModel
	 *           the index of the model within the former parent model
	 * @param formerParentModel
	 *           the former parent model of savedModel
	 * @param savedModel
	 *           the just saved model
	 * @return a {@link Couple} in which first is the new parent model and second is the model index within former parent
	 *         model
	 */
	protected Couple<STORETYPE, Integer> getNewParentModelAndIndexAfterSave(final TreeStore<STORETYPE> treeStore,
			final STORETYPE formerParentModel, final int modelIndexInFormerParentModel, final STORETYPE savedModel)
	{
		return new Couple<STORETYPE, Integer>(formerParentModel, modelIndexInFormerParentModel);
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// CALLBACKS FROM UI
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	@Override
	protected void onButtonSaveClicked()
	{
		final Timer timer = new Timer()
		{
			@Override
			public void run()
			{
				getSaveChainAction().execute();
			}
		};
		timer.schedule(150);
	}

	protected BaseAction<?> getSaveChainAction()
	{

		final BaseAction<BEANTYPE> actionSave = new BaseAction<BEANTYPE>(getLabelActionSaveLoadingLabel())
		{
			@Override
			protected void run()
			{
				getSetupDriver().accept(new DkPreFlushVisitor(true));
				final BEANTYPE updatedModel = getSetupDriver().flush();
				if (getSetupDriver().hasErrors())
				{
					MyMessageBox.alert(labelCorrectErrorsTitle, labelCorrectErrorsMessage);
					stopChain();
					onSuccess();
				}
				else
				{
					callCreateOrUpdateRpc(updatedModel, new BaseAsyncCallback<BEANTYPE>(this, true)
					{
						@Override
						public void processSuccess(final BEANTYPE result)
						{
							// Nothing to be done. Process made in chain action.
						}
					});
				}
			}
		};
		final BaseAction<BEANTYPE> actionPostSave = getPostSaveAction();
		if (actionPostSave != null)
		{
			actionSave.setLastChainAction(actionPostSave);
		}
		final BaseAction<STORETYPE> actionConvertResult = getConvertResultAction();
		if (actionConvertResult != null)
		{
			actionSave.setLastChainAction(actionConvertResult);
		}
		final BaseAction<Void> actionAfterSave = new BaseAction<Void>(DkMain.i18n().action_update_screen_loading_label())
		{
			@Override
			protected void run()
			{
				MyMessageBox.info(getLabelPopupSaveOkMessageBoxTitle(), getLabelPopupSaveOkMessageBoxMessage(),
						new MyMessageBox.AfterCloseListener()
						{
							@SuppressWarnings("unchecked")
							@Override
							public void afterClose()
							{
								onAfterSave((STORETYPE) getPreviousActionResult());
							}
						});
				onSuccess();
			}
		};
		actionSave.setLastChainAction(actionAfterSave);
		return actionSave;
	}

	@Override
	protected void onButtonCancelClicked()
	{
		onCancel();
		hide();
	}

	@Override
	protected void onButtonResetClicked()
	{
		getSetupDriver().edit(model);
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// LABELS ABSTRACT METHODS
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	@Override
	protected abstract String getLabelPopupTitle();

	protected abstract String getLabelActionSaveLoadingLabel();

	protected abstract String getLabelPopupSaveOkMessageBoxTitle();

	protected abstract String getLabelPopupSaveOkMessageBoxMessage();

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// GETTERS / SETTERS
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	/**
	 * Create (the first time) and get the driver.
	 * 
	 * @return the edition driver
	 */
	@SuppressWarnings("unchecked")
	protected DkSimpleBeanEditorDriver<BEANTYPE, EDITORTYPE> getSetupDriver()
	{
		if (driver == null)
		{
			driver = getDriver();
			driver.initialize(editor);
		}
		return driver;
	}

	/**
	 * @return the newInstanceForCreation
	 */
	public BEANTYPE getNewInstanceForCreation()
	{
		return newInstanceForCreation;
	}

	/**
	 * @param newInstanceForCreation
	 *           the newInstanceForCreation to set
	 */
	public void setNewInstanceForCreation(final BEANTYPE newInstanceForCreation)
	{
		this.newInstanceForCreation = newInstanceForCreation;
	}

	/**
	 * @return the {@link ListStore}
	 */
	protected ListStore<STORETYPE> getStore()
	{
		return this.store;
	}

	/**
	 * @return the {@link TreeStore}
	 */
	protected TreeStore<STORETYPE> getTreeStore()
	{
		return this.treeStore;
	}

	/**
	 * @return whether current action is creation or edition
	 */
	protected boolean isCreation()
	{
		return isCreation;
	}

	/**
	 * @return the editor
	 */
	public EDITORTYPE getEditor()
	{
		return editor;
	}

	protected void setLabelCorrectErrorsTitle(final String labelCorrectErrorsTitle)
	{
		this.labelCorrectErrorsTitle = labelCorrectErrorsTitle;
	}

	protected void setLabelCorrectErrorsMessage(final String labelCorrectErrorsMessage)
	{
		this.labelCorrectErrorsMessage = labelCorrectErrorsMessage;
	}

	protected BEANTYPE getModel()
	{
		return model;
	}
}
